home *** CD-ROM | disk | FTP | other *** search
- #define __DebugVersion 1
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** RamDRVR.c: Driver for RamDisk Sample
- **
- ** by Gordon Sheridan and Jim Luther
- ** modified incessantly by Brian Bechtel
- ** and even more so by Quinn "The Eskimo!"
- **
- ** File: RamDRVR.c
- **
- ** Copyright © 1992-1996 Apple Computer, Inc.
- ** All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "DTS Sample Code"
- ** after having made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the code was
- ** descended from Apple Sample Code, but that you've made changes.
- **
- ** Change History (most recent first):
- **
- ** <1.4> 19970207 Quinn Reworked to use new file layout and bring generally
- ** up-to-date.
- ** <1.3> 06/20/96 BL°B Added DriverGestalt, no OLDROUTINENAMES
- ** detailed comment on driveInfoCC call.
- ** <6> 06/10/94 BL°B Converted to work with Symantec as well.
- ** <5> 05/19/94 BL°B Converted to work with Metrowerks. Added
- ** conditionally compiled main routine for Metrowerks.
- ** <4> 10/23/93 JML Added check for valid globals before accepting
- ** Prime, Control, or Status calls (except the control
- ** and status routines that get and set the globals).
- ** <3> 10/14/93 JML Added support for the following Control and Status
- ** calls: physicalIconCC, mediaIconCC, driveInfoCC,
- ** formatListSC. driveStatusSC now returns a copy
- ** of our DrvQEl. Prime, Control and Status now checks
- ** that ioVRefNum = our drive number. Prime now updates
- ** dCtlPosition so I/O using fsFromMark will work. All
- ** debugging code now hidden with "Panic" macros. Prime
- ** now checks for block aligned I/O (since this is a
- ** block device). All calls now return appropriate error
- ** results.
- ** <2+> 7/26/93 gs Set result = noErr for Status csCode = 8.
- ** <2> 6/29/93 gs Return Drive Stats, miscellaneous clean up.
- ** <1> 6/13/93 gs Allocate space for disk from driver. Clean up comments.
- ** <0> 1/17/90 gs 11:58 PM, first version.
- **/
-
- #ifdef __MWERKS__
- #include <A4Stuff.h>
- #endif
- #ifdef THINK_C
- #include <SetupA4.h>
- #endif
-
- #include <DriverGestalt.h>
- #include <Disks.h>
-
- #include "RamDiskCommon.h"
-
- ///////////////////////////////////////////////////////////////////////////
-
- // These should be in <DriverGestalt.h>.
-
- enum {
- kdgFlush = 'flus' /* Determine if disk driver supports flush and if it needs a flush */
- };
-
- struct DriverGestaltFlushResponse {
- Boolean canFlush; /* Return true if driver supports the */
- /* kdcFlush Driver Configure _Control call */
- Boolean needsFlush; /* Return true if driver/device has data cached */
- /* and needs to be flushed when the disk volume */
- /* is flushed by the File Manager */
- UInt8 pad[2];
- };
- typedef struct DriverGestaltFlushResponse DriverGestaltFlushResponse;
-
- enum {
- kdcFlush = 'flus' /* Tell a disk driver to flush its cache and any hardware caches */
- };
-
- #define GetDriverGestaltFlushResponse(p) ((DriverGestaltFlushResponse *)(&((p)->driverGestaltResponse)))
-
- ///////////////////////////////////////////////////////////////////////////
-
- // These definitely should be a system header file somewhere!
-
- enum {
- // Common control codes
- killIOCC = 1, /* kill I/O */
- verifyDiskCC = 5, /* verify disk */
- formatDiskCC = 6, /* format disk */
- ejectDiskCC = 7, /* eject disk (ejectable media only) */
- setTagBufferCC = 8, /* set tag buffer (.SONY) */
- trackCacheCC = 9, /* control track cache (.SONY) */
- physicalIconCC = 21, /* return physical location icon and where string */
- mediaIconCC = 22, /* return media icon */
- driveInfoCC = 23, /* return drive info */
- trackDumpCC = 18244, /* diagnostic raw track dump (.SONY) */
-
- // Common status codes
- returnFormatList = 6, /* return format list (.SONY) */
- driveStatusSC = 8 /* drive status */
- };
-
- ///////////////////////////////////////////////////////////////////////////
-
- struct DriverConfigParam {
- QElemPtr qLink;
- short qType;
- short ioTrap;
- Ptr ioCmdAddr;
- ProcPtr ioCompletion;
- OSErr ioResult;
- StringPtr ioNamePtr;
- short ioVRefNum;
- short ioCRefNum; /* refNum for I/O operation */
- short csCode; /* == kDriverConfigureCode */
- OSType driverConfigureSelector;
- UInt32 driverConfigureParameter;
- };
- typedef struct DriverConfigParam DriverConfigParam;
-
- ///////////////////////////////////////////////////////////////////////////
-
- // Prototypes for main driver entry points.
-
- extern pascal OSErr DRVROpen(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
- extern pascal OSErr DRVRPrime(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
- extern pascal OSErr DRVRControl(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
- extern pascal OSErr DRVRStatus(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
- extern pascal OSErr DRVRClose(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
-
- ///////////////////////////////////////////////////////////////////////////
-
- pascal OSErr DRVROpen (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- OSErr result = noErr;
-
- #pragma unused (pb)
-
- if (!dce->dCtlStorage) /* is driver already open ? */
- {
- dce->dCtlStorage = (Handle)NewPtrSysClear(sizeof(DrvrGlobals));
- if (!(Ptr)dce->dCtlStorage)
- {
- result = MemError();
- Panic("\pDRVROpen:NewPtr returned nil");
- }
-
- globe = (DrvrGlobals *)dce->dCtlStorage;
- globe->driveNeedsFlush = false;
- }
- else
- Panic("\pDRVROpen:2nd open attempt");
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRPrime (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- unsigned long position;
- unsigned long count;
- short calltype;
- OSErr result;
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- if (globe->driveNumber != 0) /* accept no calls, before the globals are initialized */
- {
- position = dce->dCtlPosition;
- count = pb->ioParam.ioReqCount;
-
- /* Preflight the request for block alignment, size, and range */
- if (((position % 512) == 0) &&
- ((count % 512) == 0) &&
- ((count + position) <= globe->ramSize))
- {
- calltype = 0x00FF & pb->ioParam.ioTrap;
- switch(calltype)
- {
- case aRdCmd:
- /* Read the data */
- BlockMoveData(&globe->ramDisk[position], pb->ioParam.ioBuffer, count);
- break;
- case aWrCmd:
- /* Write the data */
- BlockMoveData(pb->ioParam.ioBuffer, &globe->ramDisk[position], count);
- globe->driveNeedsFlush = true;
- break;
- default:
- Panic("\pDRVRPrime: Call wasn't _Read or _Write");
- break;
- }
-
- dce->dCtlPosition += count; /* Update the position */
- pb->ioParam.ioActCount = count; /* Return the actual count */
-
- result = noErr;
- }
- else
- {
- Panic("\pDRVRPrime: Invalid block request");
- result = paramErr;
- }
- }
- else
- {
- Panic("\pDRVRPrime: Globals aren't initialized");
- result = nsDrvErr;
- }
- }
- else
- {
- Panic("\pDRVRPrime: No dCtlStorage");
- result = notOpenErr;
- }
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRControl (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- OSErr result = controlErr;
- long size;
- long i;
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- /* Accept only setGlobalsCC call, before the globals are initialized */
- if (pb->cntrlParam.csCode == setGlobalsCC)
- {
- /* Initialize DrvrGlobals */
- BlockMoveData( *(Ptr *)pb->cntrlParam.csParam,(Ptr)globe, sizeof(DrvrGlobals));
- result = noErr;
- }
- else if (globe->driveNumber != 0)
- {
- switch(pb->cntrlParam.csCode)
- {
- case killIOCC:
- /* What's there to kill? A BlockMove? sure... */
- /* We call Panic in this example; a real driver */
- /* would do something more reasonable. */
- Panic("\pDRVRControl: KillIO on Ram Disk?");
- break;
-
- case verifyDiskCC:
- result = noErr;
- break;
-
- case formatDiskCC:
- /* zero out ram disk memory */
- size = globe->ramSize / 4;
- for (i = 0 ; i < size; i++)
- ((long *)globe->ramDisk)[i] = 0;
- result = noErr;
- break;
-
- case ejectDiskCC:
- // From Martin Minow's SCSI disk sample:
- // Certain old SFGetFile calls (System 4.1?) will eject
- // disks which are marked as non-ejectable (such as this one)
- // If that happens, we need to issue a disk insert event
- // to remount the disk
- PostEvent(diskEvt, globe->driveNumber);
- break;
-
- case physicalIconCC:
- /* return pointer to icon and where string */
- *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->physicalIcon;
- result = noErr;
- break;
-
- case mediaIconCC:
- /* return pointer to icon and where string */
- *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->mediaIcon;
- result = noErr;
- break;
-
- // When a HFS volume is mounted, the File Manager calls the disk driver
- // with a "Return Drive Info" _Control call (csCode=23). Then if there
- // are no errors, it looks at the low-byte (bits 0-7) of csParam to see
- // if the drive type is ramDiskType (16, $10) or romDiskType (17, $11)
- // and if so, vcbAtDontCache is set in vcbAtrb.
- //
- // You shouldn't normally have to mess with the vcbAtDontCache bit in the
- // vcbAtrb. If you've written a RAM or ROM disk and you want the cache to
- // be bypassed, you only need to support _Control csCode 23 and say
- // you're a RAM or ROM disk. Other disk drivers probably should not mess
- // with the vcbAtDontCache bit because any improvements we make to the
- // File Manager cache will be lost on those drives (and we'll have to say
- // so when customers ask why our improvements didn't help their drives).
- //
- // See the Inside Macintosh:Files Errata technote for a discussion of this.
- case driveInfoCC:
- /* high word (bytes 2 & 3) clear */
- /* byte 1 = primary + fixed media + internal */
- /* byte 0 = drive type (0x10 = RAM disk) */
- *(unsigned long *)pb->cntrlParam.csParam = 0x00000410;
- result = noErr;
- break;
-
- case 24: /* ••• Return SCSI csCode Partition Size */
- *(unsigned long *)pb->cntrlParam.csParam = globe->ramSize >> 9;
- result = noErr;
- break;
-
- case accRun:
- result = noErr;
- break;
-
- case kDriverConfigureCode:
- switch ( ((DriverConfigParam *)pb)->driverConfigureSelector )
- {
- case kdcFlush:
- globe->driveNeedsFlush = false;
- result = noErr;
- break;
-
- default:
- break;
- }
- break;
-
- default:
- Panic("\pUnrecognized control call");
- break;
- }
- }
- else
- {
- Panic("\pDRVRControl: Globals not initialized");
- }
- }
- else
- {
- Panic("\pDRVRControl: No dCtlStorage");
- result = notOpenErr;
- }
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRStatus (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- OSErr result = statusErr;
- DrvSts *driveStats;
- DrvQElPtr driveQEl;
- DriverGestaltSyncResponse syncResponse;
- NumVersion versResponse;
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- /* Accept only getGlobalsSC call, before the globals are initialized */
- if (pb->cntrlParam.csCode == getGlobalsSC)
- {
- *(long *)pb->cntrlParam.csParam = globe->ramSize;
- if (globe->ramSize == 0)
- {
- Panic("\pDRVRStatus: ramSize is zero");
- }
- result = noErr;
- }
- else if (globe->driveNumber != 0)
- {
- switch(pb->cntrlParam.csCode)
- {
- case driveStatusSC:
- if (pb->cntrlParam.ioVRefNum != globe->driveNumber)
- break;
-
- /* Drive Stats... */
- driveStats = (DrvSts *)pb->cntrlParam.csParam;
- driveStats->track = 0; /* not applicable */
- driveStats->writeProt = 0; /* write enabled */
- driveStats->diskInPlace = 0x08; /* non-ejectable */
- driveStats->installed = 1; /* drive installed */
- driveStats->sides = 0; /* not applicable */
- driveStats->twoSideFmt = 0; /* not applicable */
- driveStats->needsFlush = 0; /* not applicable */
- driveStats->diskErrs = 0; /* not applicable */
-
- /* Copy qLink through dQFSID from our DrvQEl */
- driveQEl = (DrvQElPtr)(GetDrvQHdr()->qHead);
- while(driveQEl != nil)
- {
- if (driveQEl->dQDrive == globe->driveNumber)
- {
- driveStats->qLink = driveQEl->qLink;
- driveStats->qType = driveQEl->qType;
- driveStats->dQDrive = driveQEl->dQDrive;
- driveStats->dQRefNum = driveQEl->dQRefNum;
- driveStats->dQFSID = driveQEl->dQFSID;
-
- break; /* while(driveQEl != nil) */
- }
- driveQEl = (DrvQElPtr)(driveQEl->qLink);
- }
-
- result = noErr;
- break;
-
- case kDriverGestaltCode:
- /* We only support some information calls. A real driver */
- /* would support more of these calls, as defined in the */
- /* Designing PCI Cards & Drivers document */
- switch ( ((DriverGestaltParam *)pb)->driverGestaltSelector )
- {
- case kdgSync:
- syncResponse.behavesSynchronously = true;
- ((DriverGestaltParam *)pb)->driverGestaltResponse =
- *(unsigned long *)&syncResponse;
- result = noErr;
- break;
-
- case kdgFlush:
- {
- GetDriverGestaltFlushResponse((DriverGestaltParam *)pb)->canFlush = true;
- GetDriverGestaltFlushResponse((DriverGestaltParam *)pb)->needsFlush = globe->driveNeedsFlush;
- result = noErr;
- }
- break;
-
- case kdgVersion:
- versResponse = globe->driverVersion;
-
- ((DriverGestaltParam *)pb)->driverGestaltResponse =
- *(unsigned long *)&versResponse;
- result = noErr;
- break;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
- }
- else
- {
- Panic("\pDRVRStatus: Globals not initialized");
- }
- }
- else
- {
- Panic("\pDRVRStatus: No dCtlStorage");
- result = notOpenErr;
- }
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRClose (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
-
- #pragma unused (pb)
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- if (globe->ramDisk)
- DisposePtr(globe->ramDisk);
-
- DisposePtr((Ptr)dce->dCtlStorage);
- }
-
- return (noErr);
- }
-